package com.ww.util.json;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

public class JsonTest {

    private static final int mulThreadCount = 1000;

    private static final int count = 100000;

    /**
     * 运行结果
     * hutoolJson耗时2125毫秒
     * jackson耗时298毫秒
     * jacksonUtil耗时108毫秒
     * fastJson耗时196毫秒
     * @param args
     */
    public static void main(String[] args) {
        Map map = new HashMap<String, Object>(1000000);
        map = getMapData(map, 1000000);

        int count = JsonTest.count;

        // hutool
        long hutoolJsonBegin = System.currentTimeMillis();
        JSONUtil.toJsonStr(map);
        for (int i = 0; i < count; i++) {
            JSONUtil.toJsonStr(new HashMap<>());
        }
        long hutoolJsonEnd = System.currentTimeMillis();
        System.out.println("hutoolJson耗时" + (hutoolJsonEnd - hutoolJsonBegin) + "毫秒");

        // jackson
        long jacksonBegin = System.currentTimeMillis();
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            objectMapper.writeValueAsString(map);
            for (int i = 0; i < count; i++) {
                objectMapper.writeValueAsString(new HashMap<>());
            }
            long jacksonEnd = System.currentTimeMillis();
            System.out.println("jackson耗时" + (jacksonEnd - jacksonBegin) + "毫秒");
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        // jacksonUtil
        long jacksonBegin1 = System.currentTimeMillis();
        JsonUtil.toJsonStr(map);
        for (int i = 0; i < count; i++) {
            JsonUtil.toJsonStr(new HashMap<>());
        }
        long jacksonEnd1 = System.currentTimeMillis();
        System.out.println("jacksonUtil耗时" + (jacksonEnd1 - jacksonBegin1) + "毫秒");

        // fastJson
        long fastJsonBegin = System.currentTimeMillis();
        String s = JSONObject.toJSONString(map);
        for (int i = 0; i < count; i++) {
            JSONObject.toJSONString(new HashMap<>());
        }
        long fastJsonEnd = System.currentTimeMillis();
        System.out.println("fastJson耗时" + (fastJsonEnd - fastJsonBegin) + "毫秒");

        /**
         * jacksonUtil多线程模式最终用时249毫秒
         * FastJson多线程模式耗时242毫秒
         */
        System.out.println("------------------------------------------------");
        testMultiJacksonUtil();
        testMultiFastJson();
    }

    public static void testMultiJacksonUtil() {
        CountDownLatch countDownLatch = new CountDownLatch(mulThreadCount);
        long start = System.currentTimeMillis();
        for (int i = 0; i < mulThreadCount; i++) {
            int finalI = i;
            new Thread(() -> {
                JsonUtil.toJsonStr(new HashMap<>(1));
                countDownLatch.countDown();
            }).start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("jacksonUtil多线程模式最终用时" + (System.currentTimeMillis() - start) + "毫秒");
    }

    public static void testMultiFastJson() {
        CountDownLatch countDownLatch = new CountDownLatch(mulThreadCount);
        long start = System.currentTimeMillis();
        for (int i = 0; i < mulThreadCount; i++) {
            int finalI = i;
            new Thread(() -> {
                JSONObject.toJSONString(new HashMap<>(1));
                countDownLatch.countDown();
            }).start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("FastJson多线程模式耗时" + (System.currentTimeMillis() - start) + "毫秒");
    }

    public static Map getMapData(Map map, int count) {
        for (int i = 0; i < count; i++) {
            map.put("a" + i, i);
        }
        return map;
    }
}
